#pragma once
#include <iostream>
#include <string>
#include <memory>
#include "Log.hpp"
#include <functional>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include "Common.hpp"
#include "Internet.hpp"


namespace SocketModule
{
    class Socket;
    using SockPtr = std::shared_ptr<Socket> ;
    using namespace LogModule;
    class Socket
    {
    public:
        virtual void SocketCreate() = 0;
        virtual void SetSocketOpt() = 0;
        virtual bool BindOrDie(int port) = 0;
        virtual bool ListenOrDie() = 0;
        virtual SockPtr Accepter(InetAddr *client) = 0;
        virtual void Close() = 0;
        virtual int Recv(std::string *out) = 0;
        virtual int Send(const std::string &in) = 0;
        virtual int Fd() = 0;
      
        // 提供一个创建listensockfd的固定讨论
        void BuildTcpSocketMethod(int port)
        {
            SocketCreate();
            SetSocketOpt();
            BindOrDie(port);
            ListenOrDie();
        }

    private:
    };

    class TcpSocket : public Socket
    {
    public:
        TcpSocket(int sockfd = defaultsockfd)
            : _sockfd(sockfd)
        {
        }
        virtual void SocketCreate() override
        {
            _sockfd = ::socket(AF_INET,SOCK_STREAM,0);
            if(_sockfd < 0)
            {
                LOG(LogLevel::ERROR)<<"创捷套接字 sockfd 错误";
                return;
            }
            LOG(LogLevel::DEBUG)<<"创捷套接字 sockfd success";
        }
       
        virtual bool BindOrDie(int port) override
        {
            if (_sockfd == defaultsockfd)
                return false;
            InetAddr inetaddr(port);
            int n =::bind(_sockfd,CONV(inetaddr.Addptr()),inetaddr.Sizeptr());
            if(n<0)
            {
                LOG(LogLevel::ERROR)<<"bind false";
                return false;
            }
            LOG(LogLevel::DEBUG)<<"bind success";
            return true;
        }
        virtual void SetSocketOpt() override
        {
            // 保证我们的服务器，异常断开之后，可以立即重启，不会有bind问题
            int opt = 1;
            int n = ::setsockopt(_sockfd, SOL_SOCKET, SO_REUSEADDR,  &opt, sizeof(opt));
            (void)n;
        }
        virtual bool ListenOrDie() override
        {
            if(_sockfd == defaultsockfd)
            {
                return false;
            }
            int n = listen(_sockfd,backbag);
            if(n < 0)
            {
                LOG(LogLevel::ERROR)<<"Listen false";
                return false;
            }
            LOG(LogLevel::DEBUG)<<"Listen sucess";
            return true;
        }
        virtual SockPtr Accepter(InetAddr *client) override
        {
            if (_sockfd == defaultsockfd)
                return nullptr;
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            int n = ::accept(_sockfd,CONV(&peer),&len);
            if(n < 0)
            {
                LOG(LogLevel::ERROR)<<"accpet false";
                return nullptr;
            }
            client->SetAddr(peer);
            LOG(LogLevel::DEBUG)<<"accpet success";
            return std::make_shared<TcpSocket>(n);
        }
        virtual void Close() override
        {
            ::close(_sockfd);
        }
        virtual int Recv(std::string *out) override
        {
            if(_sockfd == defaultsockfd)
            {
                LOG(LogLevel::ERROR)<<"recv false";
                return -1;
            }
            char inbuffer[1024];
            ssize_t n = recv(_sockfd,inbuffer,sizeof(inbuffer),0);
            if(n < 0)
            {
                LOG(LogLevel::ERROR)<<"recv false";
            }
            inbuffer[n]=0;
            *out = inbuffer;
            return n;
            
        }
        virtual int Send(const std::string &in) override
        {
             if(_sockfd == defaultsockfd)
            {
                LOG(LogLevel::ERROR)<<"send false";
                return -1;
            }
            ssize_t n = send(_sockfd,in.c_str(),in.size(),0);
            if(n<0)
            {
                LOG(LogLevel::ERROR)<<"send false";
                
            }
            return n;

        }
        virtual int Fd()override
        {
            return _sockfd;
        }
    private:
        int _sockfd;
    };

}